package com.basker.pisces.core.meta.bean;

import java.lang.reflect.Method;
import java.sql.JDBCType;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.springframework.util.CollectionUtils;

import com.alibaba.fastjson.JSON;
import com.basker.pisces.core.meta.DataField;
import com.basker.pisces.core.utils.ConvertUtils;
import com.basker.pisces.utils.NumberUtils;

public class BeanDataField extends DataField {

    private BeanFieldDescriptor beanFieldDescriptor;

    public BeanDataField(BeanFieldDescriptor beanFieldDescriptor, String name, String displayName, String dbFieldName,
                         String hostTableName, boolean pkField, boolean indexField) {
        this(beanFieldDescriptor, name, displayName, dbFieldName, hostTableName, pkField, indexField, null);
    }

    public BeanDataField(BeanFieldDescriptor beanFieldDescriptor, String name, String displayName, String dbFieldName,
                         String hostTableName, boolean pkField, boolean indexField, JDBCType jdbcType) {
        super(name, displayName, dbFieldName, hostTableName, pkField, indexField, beanFieldDescriptor.getProperyType(),
                jdbcType);
        this.beanFieldDescriptor = beanFieldDescriptor;
    }

    public Method getGetMethod() {
        return beanFieldDescriptor.getGetMethod();
    }

    public Method getSetMethod() {
        return beanFieldDescriptor.getSetMethod();
    }

    @Override
    public Object getValue(Object dataObject) {
        return this.beanFieldDescriptor.getValue(dataObject);
    }

    @Override
    public void setValue(Object dataObject, Object value) {
        Object resovledValue = ConvertUtils.convert(value, this.getFieldClass());

        if (this.beanFieldDescriptor.isCollectionType()) {
            resovledValue = this.resolveItemIfNecessary(resovledValue);
        }

        this.beanFieldDescriptor.setValue(dataObject, resovledValue);
    }

    private List<Object> resolveItemIfNecessary(Object resovledValue) {
        @SuppressWarnings("unchecked")
        List<Object> listValue = (List<Object>) resovledValue;

        if (CollectionUtils.isEmpty(listValue)) {
            return listValue;
        }

        Class<?> itemType = beanFieldDescriptor.getCollectionItemType();
        if (itemType == null) {
            return listValue;
        }

        if (String.class.isAssignableFrom(itemType)) {
            // 字符串不用后续处理
            return listValue;
        }

        boolean isNumberType = Number.class.isAssignableFrom(itemType);

        @SuppressWarnings("unchecked")
        Function<? super Object, ?> mapper = item -> {
            if (item == null) {
                return null;
            }

            if (itemType.isAssignableFrom(item.getClass())) {
                return item;
            }

            if (isNumberType) {
                return NumberUtils.parse(item, (Class<? extends Number>) itemType);
            }

            return JSON.toJavaObject((JSON) item, itemType);
        };
        return listValue.stream().map(mapper).collect(Collectors.toList());
    }
}
